﻿#include "Escort.h"
#include "EscortMgr.h"
#include "MailCenter/MailManager.h"
#include "base/core/os/string.h"
#include "CenterService.h"
#include "Common/TableData/ConstantConstantCfg.h"
#include "Common/TableData/GuildescortAwardCfg.h"

Escort::Escort():
			_hostId(0),
			_escort_cid(0), 
			_type(EscortType_None), 
			_status(EscortStatus_None), 
			_speed_status(EscortSpeedStatus_None),
			_robber_status(EscortRobberStatus_None),
			_escort_level(0),
			_escort_id(0), 
			_line_id(0), 
			_robber_id(0),
			_cfg_times(0),
			_serverId(0),
			_time_last(0),
			_speed_time(0),
			_qte_time(0),
			_robber_time(0),
			_speed(0),
			_pCfg(nullptr)
{
	_repair_set.clear();
	_contri_map.clear();
	_contri_vec.clear();
}

void Escort::Init(uint32_t configId, CharIDType hostId, CharIDType cid)
{
	const GuildescortEscortCfgInfo *pCfg = g_GetGuildescortEscortCfgTable()->GetGuildescortEscortCfgInfo(configId);
	if (nullptr == pCfg)
	{
		LogErrFmtPrint("[center] Escort::Init nullptr == GuildescortEscortCfgInfo failed...configId=%u", configId);
		return;
	}
	const GuildescortRobberCfgInfo *pRcfg = g_GetGuildescortRobberCfgTable()->GetGuildescortRobberCfgInfo(pCfg->robberGangId);
	if (nullptr != pRcfg)
	{
		//LogErrFmtPrint("[center] Escort::Init nullptr == GuildescortRobberCfgInfo failed...pCfg->robberGangId=%u", pCfg->robberGangId);
		_robber_time = Random(pRcfg->minRefreshTime, pRcfg->maxRefreshTime);
		_robber_id = pCfg->robberGangId;
	}

	_hostId = hostId;
	_escort_cid = cid;
	_type = (EscortType)pCfg->teamConvoy;
	_status = EscortStatus_Running;
	_escort_id = configId;
	_time_last = pCfg->timeLimit;
	_pCfg = pCfg;
}

void Escort::Complete(bool awards)
{
	if (awards)	CalContri();
	_escort_cid = 0;				
	_type = EscortType_None;		
	_status = EscortStatus_None;
	_escort_level = 0;
	_escort_id = 0;					
	_line_id = 0;					
	_time_last = 0;
	_speed_time = 0;
	_qte_time = 0;
	_robber_time = 0;
	_speed = 0;
	_serverId = 0;;					
	_repair_set.clear();			
	_pCfg = nullptr;
}

void Escort::AddContri(CharIDType charId, uint32_t value)
{
	bool exist = false;
	ESCORT_CONTRI_VEC::iterator iter = _contri_vec.begin();
	for (; iter != _contri_vec.end(); ++iter)
	{
		if ((*iter).charId == charId)
		{
			(*iter).contri += value;
			exist = true;
			break;
		}
	}
	if (!exist)
	{
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter(charId);
		if (nullptr != pOffline)
		{
			EscortContri CharContri;
			CharContri.charId = charId;
			CharContri.contri = value;
			CharContri.charName = pOffline->GetCharName();
			_contri_vec.push_back(CharContri);
		}
	}
}

void Escort::Copy(/*const */Escort* e)
{
	_hostId = e->HostID();
	_escort_cid = e->CID();
	_type = e->Type();
	_status = e->Status();
	_speed_status = e->SpeedStatus();
	_robber_status = e->RobberStatus();
	_escort_level = e->EscortLevel();
	_escort_id = e->EscortID();
	_line_id = e->LineID();
	_robber_id = e->RobberID();
	_time_last = e->TimeLast();
	_speed_time = e->SpeedTime();
	_qte_time = e->QteTime();
	_cfg_times = e->CfgTimes();
	_serverId = e->ServerID();
	_robber_time = e->RobberTime();
	_speed = e->Speed();
	_repair_set = e->_repair_set;
	_contri_map = e->_contri_map;
	_contri_vec = e->_contri_vec;
	_pCfg = e->_pCfg;
}

inline bool CmpContri(const EscortContri &e1, const EscortContri &e2)
{
	return e1.contri > e2.contri;
}

void Escort::CalContri()
{
	if (_type != EscortType_Guild)
	{
		return;
	}
	char text2[128] = {'\0'};
	snprintf(text2, sizeof(text2), "附录1,本次活动团队护送积分前十成员:");
	string str = "";
	if (_contri_vec.size() > 0)
	{
		std::sort(std::begin(_contri_vec), std::end(_contri_vec), CmpContri);
		ESCORT_CONTRI_VEC::iterator iter = _contri_vec.begin();
		uint32_t rank = 0;
		for (; iter != _contri_vec.end(); ++iter)
		{
			char text[64] = { 0 };
			snprintf(text, sizeof(text), "    %d:%s,团队护送积分:%d\n", ++rank, (*iter).charName.c_str(), (*iter).contri);
			str += text;
		}
	}
	char text3[512] = {'\0'};
	snprintf(text3, sizeof(text3)-1, "附录2,团队护送积分获得方式:\n    1.每持续在镖车押送范围内停留10秒，可增加1点贡献度；\n    2.每修理一次公会镖车，根据镖车等级和所选修理等级将获得一定的贡献度；\n    3.在镖车押送范围内每击杀1位敌对阵营玩家即可增加一定的贡献度。！");
	string mailTitle = "军需物资护送奖励";

	LIST_ITEM items;
	ESCORT_CONTRI_VEC::iterator iter = _contri_vec.begin();
	CLActivityJoinNotify notifyJoin;
	notifyJoin.set_activityid(ESCORT_ACTIVITY_ID);
	for (; iter != _contri_vec.end(); ++iter)
	{
		OfflineCharacterData *pOffline = g_GetOfflineCharacterDataMgr()->GetOfflineCharacter((*iter).charId);
		if (nullptr == pOffline)	continue;
		items.clear();
		VecGuildescortAwardRewardsCfg *itemVec = nullptr;
		VEC_INT32 *boxIdVec = nullptr;
		const GuildescortAwardCfgMap *gMap = g_GetGuildescortAwardCfgTable()->GetGuildescortAwardCfgMap();
		if (nullptr == gMap)	continue;
		for (GuildescortAwardCfgMap::const_iterator itr = gMap->begin(); itr != gMap->end(); ++itr)
		{
			const GuildescortAwardCfgInfo &cfgInfo = itr->second;
			if ((pOffline->GetLevel() >= cfgInfo.relatedLevelMin && pOffline->GetLevel() <= cfgInfo.relatedLevelMax) && (*iter).contri >= cfgInfo.minContribution && ((*iter).contri <= cfgInfo.maxContribution || cfgInfo.maxContribution == -1))
			{
				itemVec = const_cast<VecGuildescortAwardRewardsCfg*>(&cfgInfo.vecGuildescortAwardRewardsCfg);
				boxIdVec = const_cast<VEC_INT32*>(&cfgInfo.vec_boxId);
				break;
			}
		}
		if (itemVec != nullptr)
		{
			for (VecGuildescortAwardRewardsCfg::iterator iterA = itemVec->begin(); iterA != itemVec->end(); ++iterA)
			{
				if ((*iterA).Id <= 0 || (*iterA).Num <= 0)	continue;
				SItem itemInfo;
				itemInfo.nItemID = (*iterA).Id;
				itemInfo.nNum = (*iterA).Num;
				items.push_back(itemInfo);
			}
		}
		char text1[512] = { '\0' };
		snprintf(text1, sizeof(text1)-1, "     本次公会承接的阵营军需物资已顺利送达目的地，阵营因为我们的努力又强大了一些!\n    活动中你一共获得了%d点团队护送积分，已转化为公会贡献（已发放），附件中的奖励都是你的努力换来的，感谢一路有你！", (*iter).contri);
		char mailContent[2048] = {0};
		snprintf(mailContent, sizeof(mailContent), "%s\n%s\n%s%s", text1, text2, str.c_str(), text3);
		string contentStr = mailContent;
		//g_GetMailMgr()->SendSystemMail((*iter).charId, mailTitle, contentStr, items, 0, 0, 0, 0, 0);

		SItemCond itemCond;
		itemCond.camp = pOffline->GetCampID();
		itemCond.level = pOffline->GetLevel();
		itemCond.inittype = EItemInitAttrType_Common;
		VEC_ITEM_PROTO_EX vecProtoEx;
		vecProtoEx.clear();
		g_GetItemMgr()->SetItemProtoInfo(items, vecProtoEx, itemCond);

		int32_t goldNum = 0;
		int32_t diamondNum = 0;
		int32_t bindDiamondNum = 0;
		if (boxIdVec != nullptr)
		{
			BoxCondCfg boxCond;
			g_GetOfflineCharacterDataMgr()->GetBoxCond((*iter).charId, boxCond);
			for (VEC_INT32::iterator boxIter = boxIdVec->begin(); boxIter != boxIdVec->end(); ++boxIter)
			{
				g_GetItemMgr()->CreateBoxDropItem(*boxIter, vecProtoEx, goldNum, diamondNum, bindDiamondNum, boxCond);
			}
		}

		int32_t index = vecProtoEx.size();
		VEC_ITEM_PROTO_EX temp;
		while (index > MAX_MAIL_ATTATCH_NUM)
		{
			temp.clear();
			temp.assign(vecProtoEx.begin() + vecProtoEx.size() - index, vecProtoEx.begin() + MAX_MAIL_ATTATCH_NUM);
			g_GetMailMgr()->SendSystemMail((*iter).charId, mailTitle, contentStr, goldNum, 0, diamondNum, bindDiamondNum, 0, temp, MAIL_SOURCE_UNION_ESCOTT);
			index -= MAX_MAIL_ATTATCH_NUM;
		}

		if (index > 0)
		{
			temp.clear();
			temp.assign(vecProtoEx.begin() + vecProtoEx.size() - index, vecProtoEx.end());
			g_GetMailMgr()->SendSystemMail((*iter).charId, mailTitle, contentStr, goldNum, 0, diamondNum, bindDiamondNum, 0, temp, MAIL_SOURCE_UNION_ESCOTT);
		}

		notifyJoin.set_charid((*iter).charId);
		g_GetCenterService()->SendDataToLogicByCharID((*iter).charId, EMODULE_ID_ACTIVITY, CENTER_TO_LOGIC_ACTIVITY_JOIN, &notifyJoin);
	}
}
